/* Copyright 2010 by Matt Van Der Westhuizen */

package org.chaoticengine.ast;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import org.chaoticengine.ast.model.AirShip;
import org.chaoticengine.ast.model.AirShipFactory;
import org.chaoticengine.ast.model.Location;
import org.chaoticengine.ast.model.LocationFactory;
import org.chaoticengine.ast.model.World;
import org.chaoticengine.ast.model.WorldMap;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

/**
 *
 * @author Matt Van Der Westhuizen <mattpwest@gmail.com>
 */
public class WorldGenerationState extends BasicGameState {
    @Override
    public int getID() {
        return(GameStateId.GENERATION.ordinal());
    }

    @Override
    public void enter(GameContainer container, StateBasedGame game) throws SlickException {
        GlobalData gd = GlobalData.getInstance();

        // Create the world
        World world = new World();

        // Store the world
        gd.setWorld(world);
    }

    public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
    }

    public void render(GameContainer gc, StateBasedGame sbg, Graphics grphcs) throws SlickException {
        grphcs.setColor(Color.black);
        grphcs.clear();
        grphcs.setColor(Color.white);
        grphcs.drawString("Generating map...", gc.getWidth(), gc.getHeight());
    }

    public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
        GlobalData gd = GlobalData.getInstance();

        gd.setMap(randomlyGenerateWorld(100, 100, 5));

        sbg.enterState(GameStateId.WORLD.ordinal());
    }

    protected WorldMap simplyGenerateWorld() {
        WorldMap map = new WorldMap();
        LocationFactory lf = LocationFactory.getInstance();

        Location loc = lf.getLocation("Farming Community");
        if (loc != null) {
            loc.setPosition(2, 2);
            map.addLocation(loc);
        }

        Location oldLoc = loc;
        loc = lf.getLocation("Spring");
        if (loc != null) {
            loc.setPosition(5, 5);
            map.addLocation(loc);
            map.addPath(loc, oldLoc);
        }

        oldLoc = loc;
        loc = lf.getLocation("Forest");
        System.out.println("Forest: " + loc);
        if (loc != null) {
            // TODO: 6,6 works, but 7,3 doesn't...
            //loc.setPosition(6, 6);
            loc.setPosition(7, 3);
            map.addLocation(loc);
            map.addPath(loc, oldLoc);
        }

        return(map);
    }

    protected WorldMap randomlyGenerateWorld(int width, int height, int frequency) {
        int numLocations = 0;
        Random rng = GlobalData.getInstance().getRNG();
        WorldMap map = new WorldMap();
        LocationFactory lf = LocationFactory.getInstance();

        // Create a list of possible location types
        ArrayList<String> locTypes = new ArrayList<String>();
        Iterator<String> locTypeIt = lf.getLocations().keySet().iterator();

        while (locTypeIt.hasNext()) {
            locTypes.add(locTypeIt.next());
        }

        // Generate the world locations
        for (int y = 0; y < height; y += frequency) {
            for (int x = 0; x < width; x += frequency) {
                Location loc = lf.getLocation(locTypes.get(rng.nextInt(locTypes.size())));
                loc.setPosition(x, y);
                map.addLocation(loc);
            }
        }

        // Connect the locations
        for (int y = 0; y < height; y += frequency) {
            for (int x = 0; x < width; x += frequency) {
                ArrayList<Location> neighbours = new ArrayList<Location>(4);

                Location loc = map.getLocation(x, y);
                Location nLoc = map.getLocation(x - frequency, y); // Left
                if (nLoc != null) neighbours.add(nLoc);
                nLoc = map.getLocation(x + frequency, y); // Right
                if (nLoc != null) neighbours.add(nLoc);
                nLoc = map.getLocation(x, y - frequency); // Up
                if (nLoc != null) neighbours.add(nLoc);
                nLoc = map.getLocation(x, y + frequency); // Down
                if (nLoc != null) neighbours.add(nLoc);

                for (int i = 0; i < neighbours.size(); i++) {
                    map.addPath(loc, neighbours.get(i));
                }
            }
        }

        // Move stuff around randomly
        ArrayList<Location> locations = new ArrayList<Location>();
        Iterator<Location> locIt = map.getLocations();
        while (locIt.hasNext()) {
            locations.add(locIt.next());
        }

        for (int i = 0; i < 3; i++) {
            locIt = locations.iterator();
            while (locIt.hasNext()) {
                Location loc = locIt.next();

                Vector2f p = loc.getPosition();
                map.moveLocation(loc, (int) p.x + rng.nextInt(2), (int) p.y + rng.nextInt(2));
            }
        }

        // Add the player ship
        AirShip as = AirShipFactory.getInstance().createShip("The Excalibur",
                map.getLocations().next());
        GlobalData.getInstance().setPlayerShip(as);

        return(map);
    }
}
